#include "Common/Patterns/SubscriberPublisher.hh"

#include <iostream>

#include <boost/shared_ptr.hpp>
#include <boost/bind.hpp>
#include <boost/bind/placeholders.hpp>

#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE SubscriberPublisherTests
#include <boost/test/unit_test.hpp>

using namespace Common::Patterns;

class MySubscriber : public Subscriber
{
	private:
		int iId;
	
	public:
		static int flags;

	public:
		MySubscriber( int aId ) : iId( aId ) {};

		void notify()
		{
			std::cout << "MySubscriber(" << iId << ")::notify()" << std::endl;

			int mask = 1 << (iId - 1);

			if ( flags & mask )
			{
				flags &= ~mask;
			}
		   	else
		   	{
				flags |= mask;
			}
		}
};

int MySubscriber::flags;

class Fixture
{
	public:
		Publisher::Ptr	p;
		Subscriber::Ptr	s1;
		Subscriber::Ptr	s2;
		Subscriber::Ptr	s3;

	public:
		Fixture()
		{
			MySubscriber::flags = 0;

			p  = Publisher::Ptr( new Publisher() );
			s1 = Subscriber::Ptr( new MySubscriber(1) );
			s2 = Subscriber::Ptr( new MySubscriber(2) );
			s3 = Subscriber::Ptr( new MySubscriber(3) );

			p->attach( s1 );
			p->attach( s2 );
			p->attach( s3 );
		}
};

BOOST_FIXTURE_TEST_CASE( SubscriberPublisher_Test1, Fixture )
{
	p->notifySubscribers();

	BOOST_CHECK( MySubscriber::flags == 7 );
}

BOOST_FIXTURE_TEST_CASE( SubscriberPublisher_Test2, Fixture )
{
	p->detach( s2 );
	p->notifySubscribers();

	BOOST_CHECK( MySubscriber::flags == 5 );
}

BOOST_FIXTURE_TEST_CASE( SubscriberPublisher_Test3, Fixture )
{
	s1.reset();
	p->notifySubscribers();

	BOOST_CHECK( MySubscriber::flags == 6 );
}
